/*
 *  Filename:      gsl_string.c
 *  Author:         Erick Huang<erickhuang1989@gmail.com>
 *  Revised:       2013-06-04
 *  Description:   Complement Various string handling routines for C.
 *
 *  Copyright (c) Erick Huang. All rights reserved.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "gsl_defs.h"
#include "gsl_memory.h"
#include "gsl_string.h"

#define TRACE_DEBUG_SUPPORT	
#ifdef  TRACE_DEBUG_SUPPORT
#define trdebug(format, arg...)   \
				printf("[DEBUG]"format"\n", ## arg)
#else
#define trdebug(format, arg...)   do{}while(0)
#endif

char * gsl_strdup(const char *src)
{
	UINT32 sz;
	char *ret;
	if (src == NULL)
	  return NULL;
	sz = strlen(src);
	ret = (char*)gsl_mem_alloc(sz + 1);
	memcpy(ret, src, sz);
	ret[sz] = '\0';
	return ret;
}

char * gsl_strndup(const char *src, UINT32 n)
{
	if (src == NULL)
		return NULL;
	UINT32 sz = MIN(strlen(src), n);
	char *ret = (char*)gsl_mem_alloc(sz + 1);
	memcpy(ret, src, sz);
	ret[sz] = '\0';
	return ret;
}

char * gsl_strdup_vprintf(const char *fmt, va_list ap)
{
	/* Guess we need no more than 100 bytes. */
	INT32  n, size = 100;
	char   *p, *np;

	va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/

	p = (char *)gsl_mem_alloc(size);

	while (1)
	{
		/* Try to print in the allocated space. */

		va_copy(cap, ap);
		n = vsnprintf (p, size, fmt, cap);
		va_end(cap);

		/* If that worked, return the string. */
		if (n > -1 && n < size)
			return p;
		
		//printf("Reallocing space.\n");
		/* Else try again with more space. */
		if (n > -1) /* glibc 2.1 */
			size = n + 1;	/* precisely what is needed */
		else		/* glibc 2.0 */
			size *= 2;	/* twice the old size */
		
		if ((np = (char *)realloc(p, size)) == NULL)
		{   /* failed and free space */
			gsl_mem_free(p);
			return NULL;
		}
		else
		{
			p = np;
		}
	}
}

char * gsl_strdup_printf(const char *fmt, ...)
{
	char *ret;
	va_list args;
	va_start(args, fmt);
	ret = gsl_strdup_vprintf(fmt, args);
	va_end(args);
	return ret;
}


/**
 * gsl_strcpy - 
 * @brief 
 *       "SRC" is likely to be a very big string, if "dest" space is not enough, it can cause buffer overflow, so strcpy'safe not enough.
 *
 */
char * gsl_strcpy(char *dest, const char *src)
{
	if (dest==NULL || src==NULL)
		return NULL;
	char *address = dest;
	while(( *dest++ = *src++) != '\0');
	return address;
}

/**
 * gsl_strlcpy - copy string buffer.At most (buf_size-1) characters  will be copied.
 * @param   dest - the buffer to copy to. 
 * @param   src  - the buffer to copy from. 
 * @param   buf_size -  the size of buffer to copy to.  ==> the size of dest buffer
 * @return   the length of src ==> strlen(src) 
 */
UINT32 gsl_strlcpy(char *dest, const char *src, UINT32 buf_size)
{
	UINT32 len = strlen(src);
	if (buf_size) {
		UINT32 sz = MIN(len, buf_size-1);
		memcpy(dest, src, sz);
		dest[sz] = '\0';
	}
	return len;
}



